home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / DivX / VFW4048src / src / convert.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-21  |  10.3 KB  |  389 lines

  1.  
  2. /**************************************************************************
  3.  *                                                                        *
  4.  * This code is developed by Adam Li.  This software is an                *
  5.  * implementation of a part of one or more MPEG-4 Video tools as          *
  6.  * specified in ISO/IEC 14496-2 standard.  Those intending to use this    *
  7.  * software module in hardware or software products are advised that its  *
  8.  * use may infringe existing patents or copyrights, and any such use      *
  9.  * would be at such party's own risk.  The original developer of this     *
  10.  * software module and his/her company, and subsequent editors and their  *
  11.  * companies (including Project Mayo), will have no liability for use of  *
  12.  * this software or modifications or derivatives thereof.                 *
  13.  *                                                                        *
  14.  * Project Mayo gives users of the Codec a license to this software       *
  15.  * module or modifications thereof for use in hardware or software        *
  16.  * products claiming conformance to the MPEG-4 Video Standard as          *
  17.  * described in the Open DivX license.                                    *
  18.  *                                                                        *
  19.  * The complete Open DivX license can be found at                         *
  20.  * http://www.projectmayo.com/opendivx/license.php .                      *
  21.  *                                                                        *
  22.  **************************************************************************/
  23.  
  24. /*************************************************************************
  25.  *
  26.  *  convert.cpp, image format conversion functions
  27.  *
  28.  *  Copyright (C) 2000  DivX Networks
  29.  * 
  30.  *  Adam Li
  31.  *
  32.  *  DivX Advance Research Center <darc@projectmayo.com>
  33.  *
  34.  ************************************************************************/
  35.  
  36. // This includes the functions that converts the format of the image before 
  37. // it is passed to the encore. 
  38.  
  39. #include "stdafx.h"
  40. #include "codec.h"
  41.  
  42.  
  43. int codec::getImageType(BITMAPV4HEADER *bmpinfohdr)
  44. {
  45.     // return image type codes if the image is managable
  46.     switch (bmpinfohdr->bV4V4Compression) {
  47.     case BI_RGB:
  48. //        if (bmpinfohdr->bV4BitCount == 16) return 16;
  49.         if (bmpinfohdr->bV4BitCount == 24) return 17;
  50.         if (bmpinfohdr->bV4BitCount == 32) return 18;
  51.         return 0;
  52.  
  53.     case FOURCC_UYVY:
  54.         return 32;
  55.  
  56.     case FOURCC_YUY2:
  57.     case FOURCC_YUYV:
  58.     case FOURCC_V422:
  59.         return 33;
  60.  
  61.     case FOURCC_YVYU:
  62.         return 34;
  63.  
  64.     case FOURCC_YV12:
  65.         return 64;
  66.  
  67.     case FOURCC_I420:
  68.     case FOURCC_IYUV:
  69.         return 65;
  70.  
  71.     default:
  72.         return 0;
  73.     }
  74. }
  75.  
  76.  
  77. void codec::convertImage(void *imageIn, void *imageOut, long type, long x_dim, long y_dim)
  78. {
  79.     switch (type) {
  80.     case 16:
  81.     case 17:
  82.     case 18:
  83.         convertRGB(imageIn, imageOut, type, x_dim, y_dim);
  84.         return;
  85.  
  86.     case 32:
  87.     case 33:
  88.     case 34:
  89.         convertYUV422(imageIn, imageOut, type, x_dim, y_dim);
  90.         return;
  91.  
  92.     case 64:
  93.     case 65:
  94.         convertYUV420(imageIn, imageOut, type, x_dim, y_dim);
  95.         return;
  96.  
  97.     default:
  98.         return;
  99.     }
  100. }
  101.  
  102.  
  103. /************************************************************************
  104.  *
  105.  *  int convertRGB (void *bmp, void *yuv, long type, long x_dim, long y_dim)
  106.  *
  107.  *    Purpose :    It takes a 24-bit RGB bitmap and convert it into
  108.  *                YUV (4:2:0) format
  109.  *
  110.  *  Input :        x_dim    the x dimension of the bitmap
  111.  *                y_dim    the y dimension of the bitmap
  112.  *                bmp        pointer to the buffer of the bitmap
  113.  *                yuv        pointer to the YUV structure
  114.  *
  115.  *  Output :    0        OK
  116.  *                2        memory allocation error
  117.  *
  118.  ************************************************************************/
  119.  
  120. static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
  121. static float RGBYUV01684[256], RGBYUV03316[256];
  122. static float RGBYUV04187[256], RGBYUV00813[256];
  123.  
  124. #   define  MAX(a,b)              (((a) > (b)) ? (a) : (b))
  125. #   define  CLIP(a,i,s)           (((a) > (s)) ? (s) : MAX(a,i))
  126.  
  127. int codec::convertRGB (void *bmp, void *yuv, long type, long x_dim, long y_dim)
  128. {
  129.     static int init_done = 0;
  130.  
  131.     long i, j, size, stride;
  132.     unsigned char *r, *g, *b;
  133.     unsigned char *y, *u, *v;
  134.     unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv;
  135.     unsigned char *y_buffer, *u_buffer, *v_buffer;
  136.     unsigned char *sub_u_buf, *sub_v_buf;
  137.  
  138.     if (init_done == 0)
  139.     {
  140.         InitLookupTable();
  141.         init_done = 1;
  142.     }
  143.  
  144.     // check to see if x_dim and y_dim are divisible by 2
  145.     if ((x_dim % 2) || (y_dim % 2)) return 1;
  146.     size = x_dim * y_dim;
  147.  
  148.     if (type == 17) stride = 3;
  149.     else if (type == 18) stride = 4;
  150.  
  151.     // allocate memory
  152.     y_buffer = (unsigned char *)yuv;
  153.     sub_u_buf = y_buffer + size;
  154.     sub_v_buf = y_buffer + size * 5 / 4;
  155.     u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
  156.     v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
  157.     if (!(u_buffer && v_buffer))
  158.     {
  159.         if (u_buffer) free(u_buffer);
  160.         if (v_buffer) free(v_buffer);
  161.         return 2;
  162.     }
  163.  
  164.     b = (unsigned char *)bmp;
  165.     y = y_buffer;
  166.     u = u_buffer;
  167.     v = v_buffer;
  168.  
  169.     // convert RGB to YUV
  170.     for (j = 0; j < y_dim; j ++)
  171.     {
  172.         y = y_buffer + (y_dim - j - 1) * x_dim;
  173.         u = u_buffer + (y_dim - j - 1) * x_dim;
  174.         v = v_buffer + (y_dim - j - 1) * x_dim;
  175.  
  176.         for (i = 0; i < x_dim; i ++) {
  177.             g = b + 1;
  178.             r = b + 2;
  179.             *y = (unsigned char)CLIP ((  RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]),       0, 255.f);
  180.             *u = (unsigned char)CLIP ((- RGBYUV01684[*r] - RGBYUV03316[*g] + (*b)/2          + 128), 0, 255.f);
  181.             *v = (unsigned char)CLIP ((  (*r)/2          - RGBYUV04187[*g] - RGBYUV00813[*b] + 128), 0, 255.f);
  182.             b += stride;
  183.             y ++;
  184.             u ++;
  185.             v ++;
  186.         }
  187.     }
  188.  
  189.     // subsample UV
  190.     for (j = 0; j < y_dim/2; j ++)
  191.     {
  192.         psu = sub_u_buf + j * x_dim / 2;
  193.         psv = sub_v_buf + j * x_dim / 2;
  194.         pu1 = u_buffer + 2 * j * x_dim;
  195.         pu2 = u_buffer + (2 * j + 1) * x_dim;
  196.         pv1 = v_buffer + 2 * j * x_dim;
  197.         pv2 = v_buffer + (2 * j + 1) * x_dim;
  198.         for (i = 0; i < x_dim/2; i ++)
  199.         {
  200.             *psu = (*pu1 + *(pu1+1) + *pu2 + *(pu2+1)) / 4;
  201.             *psv = (*pv1 + *(pv1+1) + *pv2 + *(pv2+1)) / 4;
  202.             psu ++;
  203.             psv ++;
  204.             pu1 += 2;
  205.             pu2 += 2;
  206.             pv1 += 2;
  207.             pv2 += 2;
  208.         }
  209.     }
  210.  
  211.     free(u_buffer);
  212.     free(v_buffer);
  213.  
  214.     return 0;
  215. }
  216.  
  217.  
  218. void codec::InitLookupTable()
  219. {
  220.     int i;
  221.  
  222.     for (i = 0; i < 256; i++) RGBYUV02990[i] = (float)0.2990 * i;
  223.     for (i = 0; i < 256; i++) RGBYUV05870[i] = (float)0.5870 * i;
  224.     for (i = 0; i < 256; i++) RGBYUV01140[i] = (float)0.1140 * i;
  225.     for (i = 0; i < 256; i++) RGBYUV01684[i] = (float)0.1684 * i;
  226.     for (i = 0; i < 256; i++) RGBYUV03316[i] = (float)0.3316 * i;
  227.     for (i = 0; i < 256; i++) RGBYUV04187[i] = (float)0.4187 * i;
  228.     for (i = 0; i < 256; i++) RGBYUV00813[i] = (float)0.0813 * i;
  229. }
  230.  
  231.  
  232. /************************************************************************
  233.  *
  234.  *  int convertYUV422 (void *bmp, void *yuv, long type, long x_dim, long y_dim)
  235.  *
  236.  *    Purpose :    It takes a YUV422 image and convert it into YUV (4:2:0) format
  237.  *
  238.  *  Input :        x_dim    the x dimension of the bitmap
  239.  *                y_dim    the y dimension of the bitmap
  240.  *                yuv422    pointer to the buffer of the yuv422 image
  241.  *                yuv        pointer to the YUV structure
  242.  *
  243.  *  Output :    0        OK
  244.  *
  245.  ************************************************************************/
  246.  
  247. int codec::convertYUV422 (void *yuv422, void *yuv, long type, long x_dim, long y_dim)
  248. {
  249.     unsigned char *line1, *line2;
  250.     unsigned char *y1, *y2, *u, *v;
  251.  
  252.     long w, h, size;
  253.  
  254.     size = x_dim * y_dim;
  255.  
  256.     h = y_dim / 2;
  257.     line1 = (unsigned char *)yuv422;                    // points to the first line
  258.     line2 = (unsigned char *)yuv422 + x_dim * 2;        // points to the second line
  259.     y1 = (unsigned char *)yuv;
  260.     y2 = (unsigned char *)yuv + x_dim;
  261.     u = (unsigned char *)yuv + size;
  262.     v = u + size / 4;
  263.  
  264.     switch (type) {
  265.     case 32:    // UYVY
  266.         while (h --) {
  267.             w = x_dim / 2;
  268.             while (w --) {
  269.                 *(u)    = (unsigned char)(((int)*(line1    ) + (int)*(line2    )) / 2);
  270.                 *(v)    = (unsigned char)(((int)*(line1 + 2) + (int)*(line2 + 2)) / 2);
  271.                 *(y1)    = *(line1 + 1);
  272.                 *(y1+1) = *(line1 + 3);
  273.                 *(y2)    = *(line2 + 1);
  274.                 *(y2+1) = *(line2 + 3);
  275.  
  276.                 u ++;
  277.                 v ++;
  278.                 y1 += 2;
  279.                 y2 += 2;
  280.                 line1 += 4;
  281.                 line2 += 4;
  282.             }
  283.             
  284.             y1 += x_dim;
  285.             y2 += x_dim;
  286.             line1 += x_dim * 2;
  287.             line2 += x_dim * 2;
  288.         }
  289.         break;
  290.  
  291.     case 33:    // YUYV YUY2 V422
  292.         while (h --) {
  293.             w = x_dim / 2;
  294.             while (w --) {
  295.                 *(u)    = (unsigned char)(((int)*(line1 + 1) + (int)*(line2 + 1)) / 2);
  296.                 *(v)    = (unsigned char)(((int)*(line1 + 3) + (int)*(line2 + 3)) / 2);
  297.                 *(y1)    = *(line1    );
  298.                 *(y1+1) = *(line1 + 2);
  299.                 *(y2)    = *(line2    );
  300.                 *(y2+1) = *(line2 + 2);
  301.  
  302.                 u ++;
  303.                 v ++;
  304.                 y1 += 2;
  305.                 y2 += 2;
  306.                 line1 += 4;
  307.                 line2 += 4;
  308.             }
  309.             
  310.             y1 += x_dim;
  311.             y2 += x_dim;
  312.             line1 += x_dim * 2;
  313.             line2 += x_dim * 2;
  314.         }
  315.         break;
  316.  
  317.     case 34:    // YVYU
  318.         while (h --) {
  319.             w = x_dim / 2;
  320.             while (w --) {
  321.                 *(v)    = (unsigned char)(((int)*(line1 + 1) + (int)*(line2 + 1)) / 2);
  322.                 *(u)    = (unsigned char)(((int)*(line1 + 3) + (int)*(line2 + 3)) / 2);
  323.                 *(y1)    = *(line1    );
  324.                 *(y1+1) = *(line1 + 2);
  325.                 *(y2)    = *(line2    );
  326.                 *(y2+1) = *(line2 + 2);
  327.  
  328.                 u ++;
  329.                 v ++;
  330.                 y1 += 2;
  331.                 y2 += 2;
  332.                 line1 += 4;
  333.                 line2 += 4;
  334.             }
  335.             
  336.             y1 += x_dim;
  337.             y2 += x_dim;
  338.             line1 += x_dim * 2;
  339.             line2 += x_dim * 2;
  340.         }
  341.         break;
  342.  
  343.     default:
  344.         break;
  345.     }
  346.  
  347.     return 0;
  348. }
  349.  
  350. /************************************************************************
  351.  *
  352.  *  int convertYUV420 (void *bmp, void *yuv, long type, long x_dim, long y_dim)
  353.  *
  354.  *    Purpose :    It takes a YUV420 image and convert it into YUV (4:2:0) format
  355.  *
  356.  *  Input :        x_dim    the x dimension of the bitmap
  357.  *                y_dim    the y dimension of the bitmap
  358.  *                yuv420    pointer to the buffer of the yuv422 image
  359.  *                yuv        pointer to the YUV structure
  360.  *
  361.  *  Output :    0        OK
  362.  *
  363.  ************************************************************************/
  364.  
  365. int codec::convertYUV420 (void *yuv420, void *yuv, long type, long x_dim, long y_dim)
  366. {
  367.     long size;
  368.     unsigned char *temp, *p1, *p2;
  369.  
  370.     if (type == 65) return 0;        // I420 IYUV no conversion needed
  371.  
  372.     // type == 64 YV12
  373.     size = x_dim * y_dim;
  374.     temp = (unsigned char *)malloc(size / 4);
  375.     if (temp == NULL) return 1;
  376.  
  377.     p1 = (unsigned char *)yuv420 + size;
  378.     p2 = p1 + size / 4;
  379.  
  380.     memcpy(temp, p1, size / 4);
  381.     memcpy(p1, p2, size / 4);
  382.     memcpy(p2, temp, size / 4);
  383.  
  384.     return 0;
  385. }
  386.  
  387.  
  388.  
  389.